
package com.gilight.base.config;
import com.gilight.base.component.CacheComponent;
import com.gilight.base.config.jwt.JwtFilter;
import com.gilight.base.config.jwt.UserRealm;
import com.gilight.base.config.jwt.cache.CustomCache;
import com.gilight.base.config.jwt.cache.CustomCacheManager;
import com.gilight.base.filter.MyAuthorizationFilter;
import com.gilight.base.filter.MyPermissionsAuthorizationFilter;
import com.gilight.base.filter.MyRolesAuthorizationFilter;
import com.gilight.base.listener.MySessionListener;
import com.gilight.base.realm.SysUserRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.*;

@Configuration
public class ShiroConfig {

/*     @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
   @Value("${spring.redis.password}")
    private String password;*/

    @Autowired
    private MySessionListener mySessionListener;
    @Autowired
    private CacheComponent cacheComponent;
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager,CacheComponent cacheComponent,@Value("${refreshTokenExpireTime}") Integer refreshTokenExpireTime) {
        // 添加自定义拦截器
        Map<String, Filter> filters = new HashMap<>();
//        filters.put("authc", new MyAuthorizationFilter());// 登录权限
//        filters.put("perms", new MyPermissionsAuthorizationFilter());// 用户操作权限
//        filters.put("roles", new MyRolesAuthorizationFilter());// 角色权限
        filters.put("jwt",new JwtFilter(cacheComponent,refreshTokenExpireTime));
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setFilters(filters);



        //拦截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不会被拦截的链接 顺序判断,anon:所有url都都可以匿名访问
        filterChainDefinitionMap.put("/index.html", "anon");
        filterChainDefinitionMap.put("/dist/**", "anon");
        filterChainDefinitionMap.put("/web/user/login", "anon");
        filterChainDefinitionMap.put("/web/user/logout", "anon");
        filterChainDefinitionMap.put("/web/cas/login", "anon");//单点登录
        filterChainDefinitionMap.put("/web/user/wxlogin", "anon");
        filterChainDefinitionMap.put("/welcome/Wpyd/imgUrl/**", "anon");
        filterChainDefinitionMap.put("/web/middleRecruit/mobile/**", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/web/icon/findIconList", "anon");
        filterChainDefinitionMap.put("/wx/lite/n/*", "anon");
        filterChainDefinitionMap.put("/web/codeGenerator", "anon");


        filterChainDefinitionMap.put("/web/coldCategory/list", "anon");
        filterChainDefinitionMap.put("/web/coldOrder/createOrder", "anon");
        filterChainDefinitionMap.put("/web/coldOrder/getOrderList", "anon");
        filterChainDefinitionMap.put("/web/app-category/**", "anon");
        filterChainDefinitionMap.put("/web/app-order/**", "anon");
        filterChainDefinitionMap.put("/web/app-coupon/**", "anon");
        filterChainDefinitionMap.put("/cb/notify/**", "anon");
        filterChainDefinitionMap.put("/web/map/qq/**", "anon");
        filterChainDefinitionMap.put("/web/app-zzjg/**", "anon");
        filterChainDefinitionMap.put("/web/app-integral/**", "anon");
        filterChainDefinitionMap.put("/web/app-product/**", "anon");
        filterChainDefinitionMap.put("/web/app-user/**", "anon");
        filterChainDefinitionMap.put("/web/app-order/get-order-in-cook-count", "anon");



        //角色控制
//        filterChainDefinitionMap.put("/web/user/hello", "authc,roles[3]");
        //权限控制
//        filterChainDefinitionMap.put("/web/user/hello", "authc,perms[4]");
        //authc:所有url都必须认证通过才可以访问;
//        filterChainDefinitionMap.put("/**", "authc");
        filterChainDefinitionMap.put("/**", "jwt");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }
//    @Bean
//    public SecurityManager securityManager() {
//        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        securityManager.setRealm(sysUserRealm());
//        securityManager.setSessionManager(sessionManager());
////        securityManager.setCacheManager(cacheManager());
//        return securityManager;
//    }
    @Bean("securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm, CustomCache customCache) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // 使用自定义Realm
        defaultWebSecurityManager.setRealm(userRealm);
        // 关闭Shiro自带的session
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        defaultWebSecurityManager.setSubjectDAO(subjectDAO);
        // 设置自定义Cache缓存
        defaultWebSecurityManager.setCacheManager(new CustomCacheManager(customCache));
        return defaultWebSecurityManager;
    }
    @Bean
    public SysUserRealm sysUserRealm() {
        SysUserRealm sysUserRealm = new SysUserRealm();
//        sysUserRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return sysUserRealm;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

/*    //配置cacheManager
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    //配置redisManager
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        redisManager.setTimeout(timeout);
//        redisManager.setPassword(password);
        redisManager.setExpire(1800);//配置缓存过期时间(秒)
        return redisManager;
    }

    //配置redisSessionDAO
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }
*/
    //配置redisSessionDAO
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        return redisSessionDAO;
    }

    @Bean
    public SessionManager sessionManager() {
//        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        ShiroSession sessionManager = new ShiroSession();
        Collection<SessionListener> listeners = new ArrayList<SessionListener>();
        listeners.add(mySessionListener);
        sessionManager.setSessionListeners(listeners);
        sessionManager.setGlobalSessionTimeout(30 * 60 * 1000);
//        sessionManager.setGlobalSessionTimeout(-1);//永不超时
        //设置redisSessionDao
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        // 指定加密方式为MD5
        credentialsMatcher.setHashAlgorithmName("MD5");
        // 加密次数
        credentialsMatcher.setHashIterations(1);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }

    /**
     * 下面的代码是添加注解支持
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        // 强制使用cglib，防止重复代理和可能引起代理出错的问题，https://zhuanlan.zhihu.com/p/29161098
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


}
